<!--
 * @Descripttion: 
 * @Author: yuxi
 * @Date: 2022-09-15 14:58:04
 * @LastEditors: yuxi
 * @LastEditTime: 2023-08-03 22:19:35
-->
<template>
  <div class="map-container">
    <MiningMap :center="center" :zoom="zoom" @pointermove="mouseMove" @dblclick="dblclick" @click="mapClick">
      <MiningTiandituLayer :ak="key" ></MiningTiandituLayer>
      <MiningWMSLayer :url="url" :layerId="layerId" ref="wms"></MiningWMSLayer>
      <MiningVectorLayer :featureStyle="pstyle">
        <MiningPoint v-if="startPoint" :feature="startPoint" :style="pstyle"></MiningPoint>
        <MiningPoint v-if="endPoint" :feature="endPoint" :style="pstyle"></MiningPoint>
        <MiningOverlay v-if="startPoint && !hasStart" :position="startPoint.getGeometry().getCoordinates()" 
        :offset="[0, -10]">           
          <template #content>
            <div style="display: flex; align-items: center; justify-content: center; flex-direction: column; gap: 10px; padding: 20px;">
              <div>确定为起点？</div>
              <el-button size="mini" type="primary" @click="hasStart = true">确定</el-button>
            </div>           
          </template>
        </MiningOverlay>

        <MiningOverlay v-if="endPoint && !hasEnd" :position="endPoint.getGeometry().getCoordinates()" 
        :offset="[0, -10]"> 
          
          <template #content>
            <div style="display: flex; align-items: center; justify-content: center; flex-direction: column; gap: 10px; padding: 20px;">
              <div>确定为终点？</div>
              <el-button size="mini" type="primary" @click="handleNext">确定</el-button>
            </div>
           
          </template>
        </MiningOverlay>
        <MiningOverlay v-if="showInfoFeature" :position="showInfoFeature.getGeometry().getCoordinates()" 
          :offset="[0, -10]"> 
          
          <template #content>
            <div style=" width: 300px; display: flex; align-items: flex-start; justify-content: center; flex-direction: column; gap: 10px; padding: 20px;">
              <div>属性信息：</div>
              <el-form ref="form"  label-width="80px">
                <el-form-item label="活动名称">
                  <el-input ></el-input>
                </el-form-item>
                <el-form-item label="活动区域">
                  <el-select   placeholder="请选择活动区域">
                    <el-option label="区域一" value="shanghai"></el-option>
                    <el-option label="区域二" value="beijing"></el-option>
                  </el-select>
                </el-form-item>
                <el-form-item>
                  <el-button type="primary" >立即创建</el-button>
                  <el-button>取消</el-button>
                </el-form-item>
              </el-form>
            </div>
           
          </template>
        </MiningOverlay>
        
      </MiningVectorLayer>
      <MiningVectorLayer  :featureStyle="style" >
        <MiningLineString  v-if="feature" :feature="feature"></MiningLineString> 

      </MiningVectorLayer>
      <MiningVectorLayer :featureStyle="style" @ready="ready" ref="layer">

        <MiningPoint v-for="(feature, index) in results" :key="index"  :feature="feature" :customContextMenus="customContextMenus"></MiningPoint>
      </MiningVectorLayer>
    </MiningMap>

    <el-dialog
      title="输入参数"
      :visible.sync="dialogVisible"
      width="30%"
      :before-close="handleCancel">
      <div>
        <p>距离：{{ distance }} m</p>
        <p>请选择颜色：        <el-color-picker v-model="stroke_color"></el-color-picker>
</p>
      </div>
      <span slot="footer" class="dialog-footer">
        <el-button @click="handleCancel">取 消</el-button>
        <el-button type="primary" @click="handleSubmit">确 定</el-button>
      </span>
  </el-dialog>
  </div>
</template>

<script>
import MiningMap from 'mining-map/Map'
import MiningTiandituLayer from 'mining-map/Layers/TiandituLayer'
import MiningVectorLayer from 'mining-map/Layers/VectorLayer'
import MiningLineString from 'mining-map/Features/LineString';
import MiningPoint from 'mining-map/Features/Point';
import MiningOverlay from 'mining-map/Overlay/Overlay';
import MiningWMSLayer from 'mining-map/Layers/WMSLayer'
import MiningWFSLayer from 'mining-map/Layers/WFSLayer'

import { GeoJSON, WFS, filter } from 'ol/format'
import { intersects } from 'ol/format/filter';

import { TiandituKey, CityCoordinates } from '@/config/config.js';
import Feature from 'ol/Feature';
import LineString from 'ol/geom/LineString';
import Point from 'ol/geom/Point';

import { Style, Stroke as StrokeStyle, Fill, Icon, Circle } from 'ol/style';
import { getArea, getLength } from 'ol/sphere.js';
import marker from '@/assets/images/marker.png'
import { exec } from '@/apis/geo'
import { Draw, Modify, Snap } from 'ol/interaction.js';
import { circular } from 'ol/geom/Polygon';
import { getDistance } from 'ol/sphere';
import * as turf from '@turf/turf'

const feature = new Feature({
  geometry: new LineString([
    CityCoordinates.BeiJing,
    CityCoordinates.TianJin,
    CityCoordinates.ShangHai,
    CityCoordinates.XiAn
  ]),
  name: 'AirLine',
});
export default {
  name: 'OptionLine',
  title: '操作线路',
  parentTitle: '业务组件',
  components: {
    MiningMap,
    MiningTiandituLayer,
    MiningVectorLayer,
    MiningLineString,
    MiningPoint,
    MiningOverlay,
    MiningWMSLayer
  },
  data () {
    const pstyle = new Style({
      stroke: new StrokeStyle({
        color: 'green',
        width: 1,
      }),
      fill: new Fill({
        color: 'green',
      }),
      image: new Circle({
        radius: 5,//半径
        fill: new Fill({//填充样式
          color: '#ff6688',
        }),
      })
    })
    const style = new Style({
      stroke: new StrokeStyle({
        color: 'green',
        width: 1,
      }),
      fill: new Fill({
        color: 'green',
      }),
      image: new Circle({
        radius: 5,//半径
        fill: new Fill({//填充样式
          color: '#2e65d2',
        }),
      })
      // image: new  Icon({
      //   anchor: [0.5, 46],
      //   anchorXUnits: 'fraction',
      //   anchorYUnits: 'pixels',
      //   src: marker,
      // })
    })
    return {
      feature: null,
      style,
      pstyle,
      url: 'http://116.196.107.252:8080/geoserver/mkdt_baode/wms',
      layerId: 'mkdt_baode:规划设计巷道-lines',
      center: [111.08663444966415, 38.95369345465808],
      zoom: 13,
      // center: [117.730311, 35.698681],
      // zoom: 5,
      key: TiandituKey,
      map: null,
      results: [],
      startPoint: null,
      endPoint: null,
      hasStart: false,
      hasEnd: false,
      active: null,
      dialogVisible: false,
      distance: '',
      stroke_color: '#2e65d2',
      layer: null,
      customContextMenus: [
        {
          name: '查看属性',
          handler: this.showInfo
        }
      ],
      showInfoFeature: null,
      wfsOptions: {
        srsName: 'EPSG:4326',
        featureNS: `http://124.71.237.248:8080/mkdt_baode`,
        featurePrefix: 'mkdt_baode',
        featureType: '规划设计巷道-lines',
        outputFormat: 'application/json',
        url: '/geoserver/wfs',
        version: '1.1.0',
        featureTypes: ['规划设计巷道-lines'],
      },
      allFeatures: []
    }
  },
  watch: {
  },
  methods: {
    ready (arg) {
      this.map = arg.map
      this.layer = arg.layer
      console.log(this.layer, arg)
      const dblClickInteraction = this.map
        .getInteractions()
        .getArray()
        .find(interaction => {
          return interaction.constructor.name === 'DoubleClickZoom'
        })
      this.map.removeInteraction(dblClickInteraction) // 取消双击放大事件
      this.fetchFeatures()
    },
    dblclick (evt) {
      let active = this.map.forEachFeatureAtPixel(
        evt.pixel,
        function (feature, layer) {
          return {
            feature: feature,
            layer: layer,
          }
        },
        {
          hitTolerance: 10,
        }
      )
      if (active) {
        // console.log(active.feature)
        this.showInfoFeature = false
        let linestring = active.feature.getGeometry()
        if (linestring instanceof Point) {
          if (this.snap) {
            this.stopModify()
          } else {
            this.startModify()
          }
        }

      }
    },
    fetchFeatures () {
      // console.log(feature.getGeometry())
      const featureRequest = new WFS().writeGetFeature({
        ...this.wfsOptions,
        // filter: intersects("geom", feature.getGeometry(), 'EPSG:4326')

      });

      fetch(this.wfsOptions.url, {
        method: 'POST',
        body: new XMLSerializer().serializeToString(featureRequest),
      })
        .then((response) => {
          return response.json();
        })
        .then((json) => {
          this.allFeatures = new GeoJSON().readFeatures(json);
          this.allFeatures = this.allFeatures.map(f => {
            let coordinate = f.getGeometry().getCoordinates()
            coordinate.splice(2);
            f.getGeometry().setCoordinates(coordinate)
            return f
          })
        });
    },
    reverseFeature (feature) {
      let newfeature = feature.clone()
      newfeature.setId(feature.getId())
      let geometry = feature.getGeometry().clone()
      let coordinates = geometry.getCoordinates()
      coordinates = coordinates.map(c => {
        if (c instanceof Array && c.length > 0) {
          if (c[0] instanceof Array) {
            return c.map(cc => {
              return [cc[1], cc[0]]
            })
          } else {
            return [c[1], c[0]]
          }
        } else {
          return c
        }

      })
      geometry.setCoordinates(coordinates)
      newfeature.setGeometry(geometry)
      return newfeature
    },
    findFeature (feature) {
      let minDistance = Infinity;
      let minIndex = 0;
      this.allFeatures.map((f, fi) => {
        var pt = turf.point(feature.getGeometry().getCoordinates());
        var line = turf.lineString(f.getGeometry().getCoordinates());

        var distance = turf.pointToLineDistance(pt, line, { units: 'miles' });
        if (minDistance > distance) {
          minDistance = distance;
          minIndex = fi;

        }
      })
      console.log(minDistance)
      if (minDistance < 0.0001) {

      }
      this.feature = this.allFeatures[minIndex]
      console.log(this.feature.getGeometry().getCoordinates())

    },
    mapClick (evt) {
      console.log(evt)
      const feature = new Feature({
        geometry: new Point(evt.coordinate),
        name: 'AirLine',
      });
      this.findFeature(feature)
      if (this.snap) return
      let active = this.map.forEachFeatureAtPixel(
        evt.pixel,
        function (feature, layer) {
          return {
            feature: feature,
            layer: layer,
          }
        },
        {
          hitTolerance: 10,
        }
      )
      if (active) {
        console.log(active.feature)
        let point = active.feature.getGeometry()
        if (point instanceof Point) {
          this.showInfoFeature = active.feature
        }

      }
    },
    mouseMove (evt) {
      let active = this.map.forEachFeatureAtPixel(
        evt.pixel,
        function (feature, layer) {
          return {
            feature: feature,
            layer: layer,
          }
        },
        {
          hitTolerance: 10,
        }
      )
      // if (active && this.feature) {
      //   console.log(active.feature)
      //   let linestring = active.feature.getGeometry()
      //   if (linestring instanceof LineString) {
      //     this.active = active.feature
      //     let point = this.getNearestPoint(linestring, evt.coordinate)
      //     this.addPoint(point)
      //     console.log(point)
      //   }

      // }
      if (this.feature) {
        let linestring = this.feature.getGeometry()
        if (linestring instanceof LineString) {
          this.active = this.feature
          let point = this.getNearestPoint(linestring, evt.coordinate)
          this.addPoint(point)
          console.log(point)
        }

      }
    },
    getNearestPoint (linestring, coordinate) {
      console.log(linestring.getCoordinates(), coordinate)
      let minDistance = Infinity;
      let minCoordinates = null;
      let minIndex = 0;
      linestring.getCoordinates().map((lcoordinate, i) => {
        const line = new LineString([lcoordinate, coordinate])
        const distance = getLength(line, {
          projection: 'EPSG:4326'
        });
        if (minDistance > distance) {
          minDistance = distance
          minCoordinates = lcoordinate
          minIndex = i
        }
      })
      let f = new Feature({
        type: 'Point',
        geometry: new Point(minCoordinates),
        name: minIndex
      })
      f.setStyle(this.pstyle)
      return f
    },

    addPoint (point) {
      if (this.hasStart && !this.hasEnd) {
        if (this.endPoint && this.endPoint.get('name') !== point.get('name')) {
          this.endPoint = null
        }
        this.$nextTick(() => {
          this.endPoint = point
        })
      } else if (!this.hasEnd) {
        if (this.startPoint && this.startPoint.get('name') !== point.get('name')) {
          this.startPoint = null
        }
        this.$nextTick(() => {
          this.startPoint = point
        })
      }
    },
    handleNext () {
      this.hasEnd = false
      this.dialogVisible = true

      const geom = this.getSplitGeom()

      const length = getLength(geom, {
        projection: 'EPSG:4326'
      });
      this.distance = length.toFixed(2)
    },
    handleCancel () {
      this.dialogVisible = false
      this.results = []
      this.hasEnd = false
      this.hasStart = false
      this.startPoint = null
      this.endPoint = null
    },
    handleSubmit () {
      const fill = this.style.getImage().getFill()
      fill.setColor(this.stroke_color)
      this.style.getImage().setFill(fill)
      console.log()
      this.dialogVisible = false
      this.split()
    },
    getSplitGeom () {
      this.hasEnd = true
      let linestring = this.active.getGeometry().clone()
      let startIndex = +this.startPoint.get('name');
      let endIndex = +this.endPoint.get('name');
      if (startIndex > endIndex) {
        [startIndex, endIndex] = [endIndex, startIndex]
      }
      let coordinates = linestring.getCoordinates()
      coordinates = coordinates.slice(startIndex, endIndex + 1);
      linestring.setCoordinates(coordinates)
      console.log(linestring)
      return linestring
    },
    split () {
      const geom = this.getSplitGeom()
      exec({
        type: 'SplitLine',
        params: {
          geom: new GeoJSON().writeGeometry(geom),
          total: 5
        }
      }).then(res => {
        if (res.code === 0) {
          let points = this.points = res.data.map(f => {
            return new GeoJSON().readFeature(f)
          })
          this.results = points
          this.startPoint = null
          this.endPoint = null
          // this.startModify()
          console.log(points)
        }
      })
    },
    startModify () {
      this.$message('开始编辑')
      this.snap = new Modify({ source: this.$refs.layer.source });
      this.map.addInteraction(this.snap);
    },
    stopModify () {
      this.$message('结束编辑')
      this.map.removeInteraction(this.snap);
      this.snap = null
    },
    showInfo () {
      console.log('showInfo')
    }
  }

}
</script>

<style>
body,
html {
  padding: 0;
  margin: 0;
}

.map-container {
  width: 100vw;
  height: 100vh;
}
</style>